/**
 * 注意添加原型方法不能用箭头函数
 */

Date.prototype.format = function(format) {
  const o = {
    "M+": this.getMonth() + 1, //月份
    "d+": this.getDate(), //日
    "H+": this.getHours(), //小时
    "m+": this.getMinutes(), //分
    "s+": this.getSeconds(), //秒
    "q+": Math.floor((this.getMonth() + 3) / 3), //季度
    "f+": this.getMilliseconds() //毫秒
  };
  if(/(y+)/.test(format))
    format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
  for(const k in o)
    if (new RegExp("(" + k + ")").test(format))
      format = format.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
  return format;
}

/**
 * @description 数组存在''\null\undefined就返回true
 */
Array.prototype.hasEmpty = function() { return Array.from(this).some(element => !element); }

/**
 * @description 把数组对折，返回两个数组
 */
Array.prototype.arrHalf = function() {
  const len = Array.from(this).length;
  const arr1Len = Math.ceil(len / 2);// 向上取整
  const arr1 = arr.slice(0, arr1Len);
  const arr2 = arr.slice(arr1Len, len + 1);
  return { arr1, arr2 }
}

/**
 * @description 指定数组中对象元素的键的值作为新数组
 * @param {string} key 
 */
Array.prototype.mapKey = function(key) { return Array.from(this).map(item => item[key]); }

/**
 * @method 获取ipv4地址
 * @param {function} resolve
 * @param {function} reject
 */
const getIPv4 = (resolve, reject) => {
	const RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection;
	if(RTCPeerConnection) {
		const rtc = new RTCPeerConnection({iceServers:[]});
		rtc.createDataChannel('', {reliable:false});
		rtc.onicecandidate = function (evt) {
			if(evt.candidate) grepSDP("a="+evt.candidate.candidate);
		};
		rtc.createOffer(function (offerDesc) {
			grepSDP(offerDesc.sdp);
			rtc.setLocalDescription(offerDesc);
		}, function (e) { console.warn("offer failed", e); });
		const addrs = [];
		addrs["0.0.0.0"] = false;
		function updateDisplay(newAddr) {
			if (newAddr in addrs) return;
			else addrs[newAddr] = true;
			const displayAddrs = Object.keys(addrs).filter(function (k) { return addrs[k]; });
			for(let i = 0; i < displayAddrs.length; i++){
				if(displayAddrs[i].length > 16){
					displayAddrs.splice(i, 1);
					i--;
				}
			}
			resolve(displayAddrs[0] || '1.0.0.0');
		}
		function grepSDP(sdp) {
			sdp.split('\r\n').forEach(function (line, index, arr) {
				if (~line.indexOf("a=candidate")) {    
					const parts = line.split(' '),       
					addr = parts[4],
					type = parts[7];
					if (type === 'host') updateDisplay(addr);
				} else if (~line.indexOf("c=")) {       
					const parts = line.split(' '),
					addr = parts[2];
					updateDisplay(addr);
				}
			});
		}
	} else {// FIXME: ie的ip地址问题
		let fakeIP = void 0;
		if(!localStorage.getItem("myCat")) {
			fakeIP = Math.random().toString(36).substr(2);
		} else {
			fakeIP = localStorage.getItem('myCat', 'Tom');
		}
		resolve('ie-' + fakeIP);
	}
}

/**
 * generator thunk自执行器
 * yield后都必须是thunk函数
 * @param {function} gen
 */
const runThunkGen = gen => {
	const g = gen();
	function next(data) {
		const result = g.next(data);
		if(result.done) return;
		result.value(next);
	}
	next();
}

/**
 * 扩展typeof
 * typeof判断[]\null\/abc/返回都是object，不是期待的
 * @param {any} val
 */
const getOPTC = content => Object.prototype.toString.call(content).replace(/^\[object |\]$/g, '').toLowerCase();

/**
 * @method json数据格式化，数组只有一个元素的得取出来
 * @param {plain-object} result
 */
const formatJson = result => {
	let message = void 0;

	try { result = JSON.parse(JSON.stringify(result)); }
	catch(err) { throw new Error(err) }

	if(Array.isArray(result)) {// array
		if(result.length === 1) {
			if(Object.prototype.toString.call(result[0]) !== '[object Object]'
				&& !Array.isArray(result[0])) {// 非object，非array
				message = result[0];
			} else {
				message = formatJson(result[0]);
			}
		} else {
			message = [];
			for(const val of result) {
				message.push(formatJson(val));
			}
		}
	} else if(typeof result === 'object') {// object
		message = {};
		for(const key in result) {// 遍历键
			if(Object.prototype.toString.call(result[key]) !== '[object Object]'
				&& !Array.isArray(result[key])) {// 简单类型
				message[key] = result[key];
			} else {
				message[key] = formatJson(result[key]);
			}
		}
	} else {// 其它类型直接返回
		message = result;
	}
  return message;
}

/**
 * @method thunk转换具有callback的函数
 */
const thunkifyCB = fn => function() {
	const args = Array.from(arguments);
	return cb => {
		args.push(cb);
		return fn.apply(this, args);
	}
}

/**
 * @method 获取浏览器信息
 */
const getBrowser = () => {
  const userAgent = navigator.userAgent; //取得浏览器的userAgent字符串 
  const isOpera = userAgent.indexOf("Opera") > -1; //判断是否Opera浏览器 
  const isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1 && !isOpera; //判断是否IE浏览器 
  const isEdge = userAgent.indexOf("Trident/7.0;") > -1 && !isIE; //判断是否IE的Edge浏览器 
  const isFF = userAgent.indexOf("Firefox") > -1; //判断是否Firefox浏览器 
  const isSafari = userAgent.indexOf("Safari") > -1 && userAgent.indexOf("Chrome") == -1; //判断是否Safari浏览器 
  const isChrome = userAgent.indexOf("Chrome") > -1 && userAgent.indexOf("Safari") > -1; //判断Chrome浏览器 

  if(isIE) {// 获取ie版本
		// const version = +userAgent.match(/(?=[\s\S]*MSIE\s+)\d+(?=\.\d+)/g)[0];
		const version = +userAgent.match(/MSIE\s+\d+/g)[0].match(/\d+/g);
    if(version >= 7) {
      return 'IE' + version;
    } else {
      return 'IE<7'
    }
  } else {
    if(isEdge) return 'Edge';
    if(isFF) return 'Firefox';
    if(isSafari) return 'Safari';
		if(isChrome) return 'Chrome';
		return void 0;
	}
}

/**
 * @method 获取日期yyyyMMddhhss格式
 */
const getDateYMDHS = () => {
	const now = new Date();

	return `
	${ now.getFullYear() }
	${ now.getMonth() + 1 }
	${ now.getDate() }
	${ now.getHours() }
	${ now.getMinutes() }
	${ now.getSeconds() }
	`.replace(/\\n|\r|\s/g, '');
}

export { getIPv4, runThunkGen, formatJson, thunkifyCB, getOPTC, getBrowser, getDateYMDHS }